package com.hup.joystick.view.functionSetting;

import com.hup.joystick.constant.FunctionConstant.FunctionType;
import com.hup.joystick.constant.FunctionConstant.MouseButton;
import com.hup.joystick.constant.FunctionConstant.MouseMoveType;
import com.hup.joystick.model.FunctionConfig.FunctionItem;
import com.hup.joystick.model.joystick.StandardEvent;
import com.hup.joystick.view.functionSetting.customView.JoyStandardKeyText;
import com.hup.joystick.view.quickMenu.setting.QuickMenuSettingDialog;
import com.hup.utils.commons.TextUtil;
import com.hup.utils.swing.customView.HComboBox;
import com.hup.utils.swing.customView.HintTextField;
import com.hup.utils.swing.customView.KeyboardText;
import lombok.Setter;
import lombok.extern.log4j.Log4j2;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.ArrayList;

/**
 * @author hugan
 * @date 2020/10/24
 */
@Log4j2
public class FunctionSettingItem extends JPanel {
    public JPanel root;
    public HintTextField txtRemark;
    public HComboBox<FunctionType> cbType;

    public HComboBox<MouseMoveType> cbMouseMoveType;
    public JButton btnQuickMenuSetting;
    public HComboBox<MouseButton> cbMouseButton;
    public KeyboardText txtKeyboardKey;
    public JoyStandardKeyText txtJoystickKey;

    @Setter
    private FunctionEditListener editListener;

    public FunctionSettingItem() {
        $$$setupUI$$$();
        initView();
        initListener();
        setFunction(null);
    }

    private void initView() {
        cbType.setItemTextHandler(type -> type.desc);
        cbType.setModel(FunctionType.values());
        cbMouseMoveType.setItemTextHandler(type -> type.desc);
        cbMouseMoveType.setModel(MouseMoveType.values());
        cbMouseButton.setItemTextHandler(type -> type.desc);
        cbMouseButton.setModel(MouseButton.values());
    }

    private void initListener() {
        txtRemark.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void insertUpdate(DocumentEvent e) {
                //log.info("insert");
                if (editListener != null) editListener.afterEditFunction();
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                //log.info("remove");
                if (editListener != null) editListener.afterEditFunction();
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                //log.info("changed");
            }
        });
        cbType.addActionListener(e -> {
            updateViewType();
            if (editListener != null) editListener.afterChangedType(cbType.getSelectedItem());
        });
        ActionListener changeListener = e -> {
            if (editListener != null) editListener.afterEditFunction();
        };
        cbMouseMoveType.addActionListener(changeListener);
        cbMouseButton.addActionListener(changeListener);
        btnQuickMenuSetting.addActionListener(e -> QuickMenuSettingDialog.showFrame());

        txtKeyboardKey.setKeyChangedListener(() -> {
            if (editListener != null) editListener.afterEditFunction();
        });
        txtJoystickKey.setKeyChangedListener(() -> {
            if (editListener != null) editListener.afterEditFunction();
        });
        txtJoystickKey.addFocusListener(new FocusListener() {
            @Override
            public void focusGained(FocusEvent e) {
                if (editListener != null) editListener.onFunctionItemFocus(FunctionSettingItem.this, true);
            }

            @Override
            public void focusLost(FocusEvent e) {
                if (editListener != null) editListener.onFunctionItemFocus(FunctionSettingItem.this, false);
            }
        });
    }

    /**
     * Method generated by IntelliJ IDEA GUI Designer
     * >>> IMPORTANT!! <<<
     * DO NOT edit this method OR call it in your code!
     *
     * @noinspection ALL
     */
    private void $$$setupUI$$$() {
        createUIComponents();
        root.setLayout(new GridBagLayout());
        cbType = new HComboBox();
        GridBagConstraints gbc;
        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = 0;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        root.add(cbType, gbc);
        final JPanel panel1 = new JPanel();
        panel1.setLayout(new GridBagLayout());
        gbc = new GridBagConstraints();
        gbc.gridx = 2;
        gbc.gridy = 0;
        gbc.weightx = 1.0;
        gbc.fill = GridBagConstraints.BOTH;
        root.add(panel1, gbc);
        cbMouseMoveType = new HComboBox();
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 2;
        gbc.weightx = 1.0;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.fill = GridBagConstraints.BOTH;
        panel1.add(cbMouseMoveType, gbc);
        txtKeyboardKey = new KeyboardText();
        txtKeyboardKey.setHint("键盘按键");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 3;
        gbc.weightx = 1.0;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.fill = GridBagConstraints.BOTH;
        panel1.add(txtKeyboardKey, gbc);
        txtJoystickKey = new JoyStandardKeyText();
        txtJoystickKey.setToolTipText("手柄按键");
        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = 1;
        gbc.gridheight = 3;
        gbc.weightx = 1.0;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        panel1.add(txtJoystickKey, gbc);
        cbMouseButton = new HComboBox();
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.weightx = 1.0;
        gbc.fill = GridBagConstraints.BOTH;
        panel1.add(cbMouseButton, gbc);
        btnQuickMenuSetting = new JButton();
        btnQuickMenuSetting.setText("设置");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.weightx = 1.0;
        gbc.fill = GridBagConstraints.BOTH;
        panel1.add(btnQuickMenuSetting, gbc);
        txtRemark = new HintTextField();
        txtRemark.setColumns(12);
        txtRemark.setToolTipText("备注");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        root.add(txtRemark, gbc);
    }

    /**
     * @noinspection ALL
     */
    public JComponent $$$getRootComponent$$$() {
        return root;
    }

    private void createUIComponents() {
        root = this;
    }

    private void updateViewType() {
        FunctionType type = cbType.getSelectedItem();
        if (type == null) type = FunctionType.NONE;
        log.debug("type={}", type);
        txtRemark.setEnabled(type != FunctionType.NONE);
        cbMouseMoveType.setVisible(type == FunctionType.MOUSE_MOVE);
        btnQuickMenuSetting.setVisible(type == FunctionType.QUICK_MENU);
        cbMouseButton.setVisible(type == FunctionType.MOUSE_BUTTON);
        txtKeyboardKey.setVisible(type == FunctionType.KEYBOARD);
        txtJoystickKey.setVisible(type == FunctionType.QUICK_MENU
                || type == FunctionType.MOUSE_BUTTON || type == FunctionType.KEYBOARD);
    }

    public void setFunction(FunctionItem function) {
        FunctionType type = function == null ? FunctionType.NONE : function.functionType;
        cbType.setSelectedItem(type);
        updateViewType();
        if (function == null) {
            txtRemark.setText(null);
            return;
        }
        txtRemark.setText(function.remark);
        switch (type) {
            case QUICK_MENU:
                txtJoystickKey.setStandardKey(function.lstStandardKey, false);
                break;
            case MOUSE_MOVE:
                cbMouseMoveType.setSelectedItem(function.mouseMoveType);
                break;
            case MOUSE_BUTTON:
                cbMouseButton.setSelectedItem(function.mouseButton);
                txtJoystickKey.setStandardKey(function.lstStandardKey, false);
                break;
            case KEYBOARD:
                txtKeyboardKey.setKeyCode(function.lstKeyCode, false);
                txtJoystickKey.setStandardKey(function.lstStandardKey, false);
                break;
        }
    }

    public String getRemark() {
        String res = txtRemark.getText();
        if (TextUtil.isBlank(res)) {
            return null;
        }
        return res.trim();
    }

    public FunctionType getType() {
        return cbType.getSelectedItem();
    }

    public ArrayList<Integer> getKeyboardCodes() {
        return txtKeyboardKey.getLstKeyCode();
    }

    public void onJoyKeyEvent(StandardEvent e) {
        txtJoystickKey.onJoyKeyEvent(e);
    }

    public ArrayList<String> getStandardKeys() {
        return txtJoystickKey.getLstStandardKey();
    }

    public interface FunctionEditListener {
        void afterChangedType(FunctionType type);

        void afterEditFunction();

        /**
         * {@link #txtJoystickKey}得到和失去焦点时触发;如果是焦点转移,则会先触发lost,后触发gained
         */
        void onFunctionItemFocus(FunctionSettingItem item, boolean isFocus);
    }

}
